Let’s import at all of the data that Simon pulled:
library(tidyverse)
Registered S3 method overwritten by 'dplyr':
method from
print.rowwise_df
[37m── [1mAttaching packages[22m ───────────────────────────── tidyverse 1.2.1 ──[39m
[37m[32m✔[37m [34mggplot2[37m 3.2.1 [32m✔[37m [34mpurrr [37m 0.3.2
[32m✔[37m [34mtibble [37m 2.1.3 [32m✔[37m [34mdplyr [37m 0.8.3
[32m✔[37m [34mtidyr [37m 1.0.0 [32m✔[37m [34mstringr[37m 1.4.0
[32m✔[37m [34mreadr [37m 1.3.1 [32m✔[37m [34mforcats[37m 0.4.0[39m
[37m── [1mConflicts[22m ──────────────────────────────── tidyverse_conflicts() ──
[31m✖[37m [34mdplyr[37m::[32mfilter()[37m masks [34mstats[37m::filter()
[31m✖[37m [34mdplyr[37m::[32mlag()[37m masks [34mstats[37m::lag()[39m
library(gridExtra)
Attaching package: ‘gridExtra’
The following object is masked from ‘package:dplyr’:
combine
library(maps)
Attaching package: ‘maps’
The following object is masked from ‘package:purrr’:
map
library(ggthemes)
DeltasClean <- read_csv("../data/out/deltas_clean_v2.csv")
Parsed with column specification:
cols(
Delta = [31mcol_character()[39m,
location = [31mcol_character()[39m,
surface = [31mcol_character()[39m,
year = [32mcol_double()[39m,
month = [32mcol_double()[39m,
ndvi = [32mcol_double()[39m,
red = [32mcol_double()[39m,
evi = [32mcol_double()[39m,
savi = [32mcol_double()[39m,
gr = [32mcol_double()[39m,
ndssi = [32mcol_double()[39m
)
DeltaLocations <- read_csv("../data/DeltaLocations.csv")
Parsed with column specification:
cols(
Deltas = [31mcol_character()[39m,
Lat = [32mcol_double()[39m,
Lon = [32mcol_double()[39m
)
As a reminder, for each of the 47 deltas there are measurements of Land & Water areas at Upstream, Downstream and ‘Middle’ locations on the delta. We first lump all the observations together, and look to see which Deltas have many observations:
#counts per delta
DeltaCounts <- count(DeltasClean, Delta)
DeltaCounts
Now, by each month.. where the colorbar represents the number of observations (n) for each month for a given delta:
DeltaObsPerMonth <- count(DeltasClean, Delta, month)
ggplot(DeltaObsPerMonth, aes(y = Delta, x = month, fill=n)) + geom_tile() +
scale_x_discrete(limits = c(1:12), breaks = c(1:12)) +
expand_limits(x = c(1,12)) +
scale_fill_gradient( trans = 'log' )

In the above heat map, dark colors (and no color) represent data paucity (and data gaps). Deltas with light colors (e.g., the Parana, Nile, Ebro, Colorado, Brahmani) have lots of data, spread out through the months of the year.
I’ll remove/subset the deltas with sparse coverage (specifically, months with no coverage)….
# need 10 data points per month for NDSSI and NDVI
EnoughObsPerMonth <- DeltasClean %>% ungroup() %>%
count(Delta, month, surface) %>%
group_by(surface) %>%
filter( n >= 5)
#find deltas missing a given month of observations
DeltaMonthCounts <- EnoughObsPerMonth %>%
ungroup() %>%
count(Delta)
# need 12 months of water and land obs, so 24 mo total
EnoughMonths <- DeltaMonthCounts %>%
filter( n == 24)
CompleteObsDeltas <- pull(EnoughMonths, Delta)
#remove them
DeltasCleaner <- DeltasClean %>%
filter(Delta %in% CompleteObsDeltas)
#add the real dates in month date format
DeltasCleaner$date <- as.Date(paste(DeltasCleaner$year, DeltasCleaner$month, "01", sep="-"), "%Y-%m-%d")
#remove intermediate data
rm(CompleteObsDeltas, EnoughMonths, DeltaMonthCounts)
#EnoughMonths
and extract some metrics; specifically I will make a timeseries of NDVI and NDSSI for each delta using the mean value for each month.
#take the mean NDVI and NDSSI for each month, for each delta
DeltaMeans <- DeltasCleaner %>%
group_by(Delta, month, surface) %>%
summarize(MeanNDVI = mean(ndvi, na.rm = TRUE), MeanNDSSI = mean(ndssi, na.rm = TRUE))
#make a 9 column data frame with:
#delta,
#max and min NDVI month,
#NDSSI max and min month,
#max and min values for both NDVI and NDSSI
#####
DeltaMaxNDVI <-
DeltaMeans %>%
filter(surface == 'Land') %>%
select (-c(MeanNDSSI)) %>%
group_by(Delta) %>%
slice(which.max(MeanNDVI)) %>%
rename(MaxMeanNDVImonth = month, MaxMeanNDVI = MeanNDVI)
DeltaMaxNDSSI <-
DeltaMeans %>%
filter(surface == 'Water') %>%
select (-c(MeanNDVI)) %>%
group_by(Delta) %>%
slice(which.max(MeanNDSSI)) %>%
rename(MaxMeanNDSSImonth = month, MaxMeanNDSSI = MeanNDSSI)
DeltaMinNDVI <-
DeltaMeans %>%
filter(surface == 'Land') %>%
select (-c(MeanNDSSI)) %>%
group_by(Delta) %>%
slice(which.min(MeanNDVI)) %>%
rename(MinMeanNDVImonth = month, MinMeanNDVI = MeanNDVI)
DeltaMinNDSSI <-
DeltaMeans %>%
filter(surface == 'Water') %>%
select (-c(MeanNDVI)) %>%
group_by(Delta) %>%
slice(which.min(MeanNDSSI)) %>%
rename(MinMeanNDSSImonth = month, MinMeanNDSSI = MeanNDSSI)
#join into 1 dataframe
DeltaMaxMin <- left_join(DeltaMaxNDVI, DeltaMaxNDSSI, by = 'Delta') %>%
left_join(.,DeltaMinNDVI, by = 'Delta') %>%
left_join(.,DeltaMinNDSSI, by = 'Delta')
#remove intermediate data
rm(DeltaMaxNDVI, DeltaMaxNDSSI, DeltaMinNDSSI,DeltaMinNDVI)
And now we can look at the phase shifts between these two time series (the timeseries of mean NDVI and mean NDSSI). Here are the phase shifts (in month) for each delta:
#compare offset
DeltaMaxMin <- mutate(DeltaMaxMin,
MinOffset = if_else(abs(MinMeanNDVImonth - MinMeanNDSSImonth) > 6,
12 - abs(MinMeanNDVImonth - MinMeanNDSSImonth),
abs(MinMeanNDVImonth - MinMeanNDSSImonth)),
MaxOffset = if_else(abs(MaxMeanNDVImonth - MaxMeanNDSSImonth) > 6,
12 - abs(MaxMeanNDVImonth - MaxMeanNDSSImonth),
abs(MaxMeanNDVImonth - MaxMeanNDSSImonth)),
OffsetDiff = abs(MaxOffset - MinOffset),
rangeNDVI = (MaxMeanNDVI - MinMeanNDVI),
rangeNDSSI = (MaxMeanNDSSI - MinMeanNDSSI),
halfPeriodNDVI = if_else(abs(MaxMeanNDVImonth - MinMeanNDVImonth) > 6,
12 - abs(MaxMeanNDVImonth - MinMeanNDVImonth),
abs(MaxMeanNDVImonth - MinMeanNDVImonth)),
halfPeriodNDSSI = if_else(abs(MaxMeanNDSSImonth - MinMeanNDSSImonth) > 6,
12 - abs(MaxMeanNDSSImonth - MinMeanNDSSImonth),
abs(MaxMeanNDSSImonth - MinMeanNDSSImonth)), )
# DeltaMaxMin <-
# DeltaMaxMin %>%
# select (c(Delta, MinOffset, MaxOffset, OffsetDiff, rangeNDVI, rangeNDSSI,MaxMeanNDSSI,MinMeanNDSSI,MaxMeanNDVI,MinMeanNDVI))
DeltaMaxMin
ggplot(DeltaMaxMin, aes(y = Delta, x = MaxOffset)) + geom_point() +
scale_x_discrete(limits = c(1:6), breaks = c(1:6)) +
expand_limits(x = c(0,6)) +
ggtitle("MaxOffset")

ggplot(DeltaMaxMin, aes(y = Delta, x = MinOffset)) + geom_point() +
scale_x_discrete(limits = c(1:6), breaks = c(1:6)) +
expand_limits(x = c(0,6)) +
ggtitle("MinOffset")

ggplot(DeltaMaxMin, aes(y = Delta, x = OffsetDiff)) + geom_point() +
scale_x_discrete(limits = c(1:6), breaks = c(1:6)) +
expand_limits(x = c(0,6)) +
ggtitle("Offset Difference")

Now let’s examine the histograms of all 31 deltas… The months with the greatest mean NDVI, months with gretaest mean NDSSI, the monthly offset, and the skew of the NDSSI and NDVI timeseries.
ggplot(DeltaMaxMin, aes(x = MaxMeanNDVImonth)) +
geom_dotplot(binwidth = 1,dotsize = 0.5) +
scale_y_continuous(NULL, breaks = NULL) +
scale_x_discrete(limits = c(1:12), breaks = c(1:12)) +
labs(x = "Month") +
ggtitle("Month of maximum mean NDVI")

ggplot(DeltaMaxMin, aes(x = MaxMeanNDSSImonth)) +
geom_dotplot(binwidth = 1,dotsize = 0.5) +
scale_y_continuous(NULL, breaks = NULL) +
scale_x_discrete(limits = c(1:12), breaks = c(1:12)) +
labs(x = "Month") +
ggtitle("Month of maximum mean NDSSI")

ggplot(DeltaMaxMin, aes(x = MaxOffset)) +
geom_dotplot(binwidth = 1,dotsize = 0.25) +
scale_y_continuous(NULL, breaks = NULL) +
scale_x_discrete(limits = c(0:6), breaks = c(0:6)) +
labs(x = "Months") +
ggtitle("Months Offset between NDVI and NDSSI")

ggplot(DeltaMaxMin, aes(x = halfPeriodNDVI)) +
geom_dotplot(binwidth = 1,dotsize = 0.25) +
scale_y_continuous(NULL, breaks = NULL) +
scale_x_discrete(limits = c(0:6), breaks = c(0:6)) +
labs(x = "Months") +
ggtitle("half period NDVI ")

ggplot(DeltaMaxMin, aes(x = halfPeriodNDSSI)) +
geom_dotplot(binwidth = 1,dotsize = 0.25) +
scale_y_continuous(NULL, breaks = NULL) +
scale_x_discrete(limits = c(0:6), breaks = c(0:6)) +
labs(x = "Months") +
ggtitle("half period NDSSI")

Ok, so the idea is that peak NDSSI is more effective if it occurs at moderate NDVI, so let’s look at the NDVI value for the months with peak NDSSI.
#extract NDVI value for each delta a the month of max NDSSI value
DeltaNDVIatMaxNDSSI <- DeltaMaxMin %>%
select(Delta,MaxMeanNDSSImonth)
DeltaMeansToJoin <- DeltaMeans %>%
filter(surface == 'Land')
DeltaNDVIatMaxNDSSI <- left_join(DeltaNDVIatMaxNDSSI, DeltaMeansToJoin,
by = c('Delta', 'MaxMeanNDSSImonth' ='month'))
DeltaNDVIatMaxNDSSI <- DeltaNDVIatMaxNDSSI %>%
select (-c(surface, MeanNDSSI))
DeltaNDVIatMaxNDSSI
ggplot(DeltaNDVIatMaxNDSSI, aes(x = MeanNDVI)) +
geom_dotplot(binwidth = 0.1, dotsize = 0.25) +
scale_y_continuous(NULL, breaks = NULL) +
xlim(0,1) +
labs(x = "NDVI") +
ggtitle("NDVI at month of maximum mean NDSSI")

How about the NDVI for months with the lowest NDSSI
#extract NDVI value for each delta a the month of min NDSSI value
DeltaNDVIatMinNDSSI <- DeltaMaxMin %>%
select(Delta,MinMeanNDSSImonth)
DeltaMeansToJoin <- DeltaMeans %>%
filter(surface == 'Land')
DeltaNDVIatMinNDSSI <- left_join(DeltaNDVIatMinNDSSI, DeltaMeansToJoin,
by = c('Delta', 'MinMeanNDSSImonth' ='month'))
DeltaNDVIatMinNDSSI <- DeltaNDVIatMinNDSSI %>%
select (-c(surface, MeanNDSSI))
DeltaNDVIatMaxNDSSI
ggplot(DeltaNDVIatMinNDSSI, aes(x = MeanNDVI)) +
geom_dotplot(binwidth = 0.1, dotsize = 0.25) +
scale_y_continuous(NULL, breaks = NULL) +
xlim(0,1) +
labs(x = "NDVI") +
ggtitle("NDVI at month of min mean NDSSI")

Just to explore the data a bit, here are the phase shifts/offsets against other measured parameters for each delta. The range, max and mean of NDVI and NDSSI is calculated from the timeseries, so it is really the max, min, and range of the monthly means (i.e., the maximum of the means, the minimum of the means, and the range of the mean). Offset is measured in months.
slice1 <- ggplot(DeltaMaxMin, aes(y = rangeNDVI, x = MaxOffset)) + geom_point()
# + scale_x_discrete(limits = c(1:6), breaks = c(1:6)) + expand_limits(x = c(1,6))
slice2 <- ggplot(DeltaMaxMin, aes(y = rangeNDVI, x = rangeNDSSI)) + geom_point()
slice3 <- ggplot(DeltaMaxMin, aes(y = rangeNDSSI, x = MaxOffset)) + geom_point()
slice4 <- ggplot(DeltaMaxMin, aes(y = MaxMeanNDVI, x = rangeNDVI)) + geom_point()
slice5 <- ggplot(DeltaMaxMin, aes(y = MaxMeanNDVI, x = rangeNDSSI)) + geom_point()
slice6 <- ggplot(DeltaMaxMin, aes(y = MaxMeanNDVI, x = MaxOffset)) + geom_point()
slice7 <- ggplot(DeltaMaxMin, aes(y = MaxMeanNDSSI, x = MaxMeanNDVI)) + geom_point()
slice8 <- ggplot(DeltaMaxMin, aes(y = MaxMeanNDSSI, x = rangeNDSSI)) + geom_point()
slice9 <- ggplot(DeltaMaxMin, aes(y = MaxMeanNDSSI, x = MaxOffset)) + geom_point()
slice10 <- ggplot(DeltaMaxMin, aes(y = MaxMeanNDSSI, x = rangeNDVI)) + geom_point()
grid.arrange(slice1, slice2, slice3, slice4, slice5, slice6, ncol=3)

grid.arrange(slice7, slice8, slice9, slice10, ncol=2)

#remove those panels
rm(slice1, slice2, slice3, slice4, slice5, slice6,slice7, slice8, slice9, slice10)
Join Latitude and longitude data
DeltaDatawLocations <- left_join(DeltaMaxMin, DeltaLocations, by = c("Delta" = "Deltas"))
DeltaDatawLocations <- DeltaDatawLocations %>%
mutate(Absolute_Latitude= abs(Lat))
plot params vs lat
loc1 <- ggplot(DeltaDatawLocations, aes(y = Absolute_Latitude, x = MaxOffset)) + geom_point()
loc2 <- ggplot(DeltaDatawLocations, aes(y = Absolute_Latitude, x = rangeNDSSI)) + geom_point()
loc3 <- ggplot(DeltaDatawLocations, aes(y = Absolute_Latitude, x = rangeNDVI)) + geom_point()
loc4 <- ggplot(DeltaDatawLocations, aes(y = Absolute_Latitude, x = MaxMeanNDVI)) + geom_point()
loc5 <- ggplot(DeltaDatawLocations, aes(y = Absolute_Latitude, x = MaxMeanNDSSI)) + geom_point()
grid.arrange(loc1, loc2, loc3, loc4, loc5, ncol=2)

loc1

#ggsave("loc1.pdf", width = 4, height = 4)
loc2

#ggsave("loc2.pdf", width = 4, height = 4)
loc3

#ggsave("loc3.pdf", width = 4, height = 4)
#remove those panels
rm(loc1, loc2, loc3, loc4, loc5)
#find the linear model
DeltaOffset_lm <- lm( Absolute_Latitude ~ MaxOffset, data = DeltaDatawLocations)
summary(DeltaOffset_lm)
Call:
lm(formula = Absolute_Latitude ~ MaxOffset, data = DeltaDatawLocations)
Residuals:
Min 1Q Median 3Q Max
-21.779 -8.983 0.775 8.377 20.772
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 10.820 4.629 2.337 0.02653 *
MaxOffset 4.079 1.157 3.525 0.00143 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 11.06 on 29 degrees of freedom
Multiple R-squared: 0.2999, Adjusted R-squared: 0.2758
F-statistic: 12.43 on 1 and 29 DF, p-value: 0.001428
ggplot(DeltaDatawLocations, aes(x = Absolute_Latitude, y = MaxOffset)) +
geom_point() +
geom_smooth(mapping = aes(x = Absolute_Latitude, y = MaxOffset, ), method=lm )

NA
NA
NA
Now for some maps of the data maps:
world <- ggplot() +
borders("world", colour = "gray85", fill = "gray80") +
theme_map()
DeltaOffsetMap <- world +
geom_point(aes(x = Lon, y = Lat, color = MaxOffset),
data = DeltaDatawLocations,
size = 5) + scale_color_gradient( high = "red", low = "yellow") +
ggtitle("Offset Between NDVI peak on Land and NDSSI peak in water")
DeltaOffsetMap

#ggsave("DeltaOffsetMap.pdf", width = 6, height = 4)
world <- ggplot() +
borders("world", colour = "gray85", fill = "gray80") +
theme_map()
DeltaNDVIrangeMap <- world +
geom_point(aes(x = Lon, y = Lat, color = rangeNDVI),
data = DeltaDatawLocations,
size = 5) + scale_color_gradient( high = "red", low = "yellow") +
ggtitle("NDVI range")
DeltaNDSSIrangeMap <- world +
geom_point(aes(x = Lon, y = Lat, color = rangeNDSSI),
data = DeltaDatawLocations,
size = 5) + scale_color_gradient( high = "red", low = "yellow") + ggtitle("NDSSI range")
DeltaNDVIrangeMap

#ggsave("DeltaNDVIrangeMap.pdf", width = 6, height = 4)
DeltaNDSSIrangeMap

#ggsave("DeltaNDSSIrangeMap.pdf", width = 6, height = 4)
Let’s look at some of the timeseries To quantify the water, we use NDSSI. to quantify land, we use NDVI.
First here is the function to make the plots:
DeltaPlotter <- function(DeltaName) {
#Counts each month
numVeg <- DeltasCleaner %>%
select(Delta, surface, month, ndvi) %>%
filter(Delta == DeltaName & surface == "Land" & !is.na(ndvi)) %>%
group_by(month) %>%
summarize(n = n())
numSed <- DeltasCleaner %>%
select(Delta, surface, month, ndssi) %>%
filter(Delta == DeltaName &
surface == "Water" & !is.na(ndssi)) %>%
group_by(month) %>%
summarize(n = n())
#Highlight the Maximum and Minimum Month for each delta, NDVI and NDSSI
#LAND
Veg <-
ggplot(data = filter(DeltasCleaner, Delta == DeltaName &
surface == "Land")) +
geom_boxplot(aes(x = month, y = ndvi, group = month)) +
scale_x_discrete(limits = c(1:12), breaks = c(1:12)) +
expand_limits(x = c(1, 12)) +
ggtitle(DeltaName) +
#geom_text(data = numVeg, aes(y = 1.05, x = month, label = n)) +
geom_boxplot(
data = filter(
DeltasCleaner,
Delta == DeltaName &
surface == "Land" & month == DeltaMaxMin$MaxMeanNDVImonth[DeltaMaxMin$Delta == DeltaName]
),
aes(x = month, y = ndvi, group = month),
fill = "green"
) +
geom_boxplot(
data = filter(
DeltasCleaner,
Delta == DeltaName &
surface == "Land" & month == DeltaMaxMin$MinMeanNDVImonth[DeltaMaxMin$Delta ==DeltaName]
),
aes(x = month, y = ndvi, group = month),
fill = "blue"
)
Sed <-
ggplot(data = filter(DeltasCleaner, Delta == DeltaName &
surface == "Water")) +
geom_boxplot(aes(x = month, y = ndssi, group = month)) +
scale_x_discrete(limits = c(1:12), breaks = c(1:12)) +
expand_limits(x = c(1, 12)) +
#geom_text(data = numSed, aes(y = 1.05, x = month, label = n)) +
geom_boxplot(
data = filter(
DeltasCleaner,
Delta == DeltaName &
surface == "Water" & month == DeltaMaxMin$MaxMeanNDSSImonth[DeltaMaxMin$Delta == DeltaName]
),
aes(x = month, y = ndssi, group = month),
fill = "green"
) +
geom_boxplot(
data = filter(
DeltasCleaner,
Delta == DeltaName &
surface == "Water" & month == DeltaMaxMin$MinMeanNDSSImonth[DeltaMaxMin$Delta == DeltaName]
),
aes(x = month, y = ndssi, group = month),
fill = "blue"
)
return(grid.arrange(Veg, Sed, nrow = 2))
}
Here is are some examples:
- The peaks in both timeseries shift around depending on the delta:
- look at the correlation in the Orinoco nad Senegal
- The anticorrelation in the Parana and Ebro,
- The slight phase shift in the Magdalena.
DeltaPlotter("Parana")

DeltaPlotter("Magdalena")

DeltaPlotter("Ebro")

DeltaPlotter("Nile")

DeltaPlotter("Senegal")

DeltaPlotter("Orinoco")

DeltaPlotter("Godavari")

DeltaPlotter("Krishna")

Now for some work with GRDC discharge data:
#import the data (monthly means for 21 stations)
DeltasGRDC <- read_csv("../data/GRDCstations.csv")
Parsed with column specification:
cols(
Deltas = [31mcol_character()[39m,
GRDC_Station = [32mcol_double()[39m,
Time_Series_Length = [31mcol_character()[39m,
January = [32mcol_double()[39m,
February = [32mcol_double()[39m,
March = [32mcol_double()[39m,
April = [32mcol_double()[39m,
May = [32mcol_double()[39m,
June = [32mcol_double()[39m,
July = [32mcol_double()[39m,
August = [32mcol_double()[39m,
September = [32mcol_double()[39m,
October = [32mcol_double()[39m,
November = [32mcol_double()[39m,
December = [32mcol_double()[39m
)
#calculate the mean of the monthly means
DeltasGRDCwMean <- DeltasGRDC %>%
rowwise() %>%
mutate(MMD=mean(c(January,February,March,April,
May,June,July,August,
September,October,November,December)))
DeltasGRDCwMean <- DeltasGRDCwMean %>%
rowwise() %>%
mutate(Range_Discharge = max(c(January,February,March,April,
May,June,July,August,
September,October,November,December)) -
min(c(January,February,March,April,
May,June,July,August,
September,October,November,December))
)
#join to location data:
DeltawLocGRDC <- left_join(DeltaDatawLocations, DeltasGRDCwMean, by = c("Delta" = "Deltas"))
#plot mean of monthly means against NDSSI
ggplot(DeltawLocGRDC, aes(y = Range_Discharge, x = rangeNDSSI)) + geom_point() + scale_y_continuous(trans='log10')

#ggsave("GRDCNDSSI.pdf", width = 6, height = 4)
ggplot(DeltawLocGRDC, aes(y = Range_Discharge, x = MaxMeanNDSSI)) + geom_point() + scale_y_continuous(trans='log10')

#rename the months by numbers and tidy the GRDC data
DeltasDischarge <- DeltasGRDC %>%
rename(Delta = Deltas,"1" = January, "2"= February, "3"= March, "4"= April,
"5"=May, "6"=June, "7"=July, "8"= August, "9" = September, "10"=October,
"11"=November, "12"=December) %>%
select(Delta, "1" , "2" , "3", "4","5", "6", "7", "8", "9", "10", "11", "12") %>%
pivot_longer(-Delta, names_to = "month", values_to = "discharge")
#find max GRDC month for each delta
DeltaMaxDischarge <-
DeltasDischarge %>%
group_by(Delta) %>%
slice(which.max(discharge)) %>%
rename(MaxDischargeMonth = month, MaxDischarge = discharge)
DeltaMaxDischarge$MaxDischargeMonth = as.numeric(DeltaMaxDischarge$MaxDischargeMonth)
#join with other delta data
DeltaMaxMinDischarge <- left_join(DeltaMaxMin, DeltaMaxDischarge, by = 'Delta')
#calculate offset
DeltaMaxMinDischarge <- DeltaMaxMinDischarge %>%
mutate( DissOff = if_else(abs(MaxDischargeMonth - MaxMeanNDSSImonth) > 6,
12 - abs(MaxDischargeMonth - MaxMeanNDSSImonth),
abs(MaxDischargeMonth - MaxMeanNDSSImonth))
)
#Compare offset with NDSSI (deltamaxmin$maxmeanNDSSImonth)
ggplot(DeltaMaxMinDischarge, aes(y = Delta, x = DissOff)) + geom_point() +
scale_x_discrete(limits = c(1:6), breaks = c(1:6)) +
expand_limits(x = c(0,6)) +
ggtitle("DisOffset")

Look at GRDC data by latitude:
#join lat data
DeltaDatawLocations <- left_join(DeltaMaxMinDischarge, DeltaLocations, by = c("Delta" = "Deltas"))
DeltaDatawLocations <- DeltaDatawLocations %>%
mutate(Absolute_Latitude= abs(Lat))
# plot offset on graph by lat
ggplot(DeltaDatawLocations, aes(x = Absolute_Latitude, y = DissOff)) + geom_point() +
scale_color_gradient(low = "yellow", high = "red", na.value = NA)

#+ geom_smooth(mapping = aes(x = Absolute_Latitude, y = DissOff, ), method=lm )
#ggsave("DisOffset.pdf", width = 6, height = 4)
And now on a map:
#plot offset on map
DeltaDisOffsetMap <- world +
geom_point(aes(x = Lon, y = Lat, color = DissOff),
data = DeltaDatawLocations,
size = 5) + scale_color_gradient( high = "red", low = "yellow") +
ggtitle("Offset Between GRDC discharge peak and NDSSI peak in water")
DeltaDisOffsetMap

#ggsave("DeltaOffsetMap.pdf", width = 6, height = 4)
LS0tCnRpdGxlOiAiRGVsdGFzIE5vdGVib29rIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKICB3b3JkX2RvY3VtZW50OiBkZWZhdWx0CmVkaXRvcl9vcHRpb25zOiAKICBjaHVua19vdXRwdXRfdHlwZTogaW5saW5lCi0tLQoKTGV0J3MgaW1wb3J0IGF0IGFsbCBvZiB0aGUgZGF0YSB0aGF0IFNpbW9uIHB1bGxlZDoKCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkobWFwcykKbGlicmFyeShnZ3RoZW1lcykKCkRlbHRhc0NsZWFuIDwtIHJlYWRfY3N2KCIuLi9kYXRhL291dC9kZWx0YXNfY2xlYW5fdjIuY3N2IikgCkRlbHRhTG9jYXRpb25zIDwtIHJlYWRfY3N2KCIuLi9kYXRhL0RlbHRhTG9jYXRpb25zLmNzdiIpCmBgYAoKQXMgYSByZW1pbmRlciwgZm9yIGVhY2ggb2YgdGhlIDQ3IGRlbHRhcyB0aGVyZSBhcmUgbWVhc3VyZW1lbnRzIG9mIExhbmQgJiBXYXRlciBhcmVhcyBhdCBVcHN0cmVhbSwgRG93bnN0cmVhbSBhbmQgJ01pZGRsZScgbG9jYXRpb25zIG9uIHRoZSBkZWx0YS4gV2UgZmlyc3QgbHVtcCBhbGwgdGhlIG9ic2VydmF0aW9ucyB0b2dldGhlciwgYW5kIGxvb2sgdG8gc2VlIHdoaWNoIERlbHRhcyBoYXZlIG1hbnkgb2JzZXJ2YXRpb25zOgoKYGBge3J9CiNjb3VudHMgcGVyIGRlbHRhCkRlbHRhQ291bnRzIDwtIGNvdW50KERlbHRhc0NsZWFuLCBEZWx0YSkKRGVsdGFDb3VudHMKYGBgCgoKTm93LCBieSBlYWNoIG1vbnRoLi4gd2hlcmUgdGhlIGNvbG9yYmFyIHJlcHJlc2VudHMgdGhlIG51bWJlciBvZiBvYnNlcnZhdGlvbnMgKG4pIGZvciBlYWNoIG1vbnRoIGZvciBhIGdpdmVuIGRlbHRhOgpgYGB7cn0KRGVsdGFPYnNQZXJNb250aCA8LSBjb3VudChEZWx0YXNDbGVhbiwgRGVsdGEsIG1vbnRoKQoKZ2dwbG90KERlbHRhT2JzUGVyTW9udGgsIGFlcyh5ID0gRGVsdGEsIHggPSBtb250aCwgZmlsbD1uKSkgKyBnZW9tX3RpbGUoKSArIAogIHNjYWxlX3hfZGlzY3JldGUobGltaXRzID0gYygxOjEyKSwgYnJlYWtzID0gYygxOjEyKSkgKwogIGV4cGFuZF9saW1pdHMoeCA9IGMoMSwxMikpICsgCiAgc2NhbGVfZmlsbF9ncmFkaWVudCggdHJhbnMgPSAnbG9nJyApCgpgYGAKCgpJbiB0aGUgYWJvdmUgaGVhdCBtYXAsIGRhcmsgY29sb3JzIChhbmQgbm8gY29sb3IpIHJlcHJlc2VudCBkYXRhIHBhdWNpdHkgKGFuZCBkYXRhIGdhcHMpLiBEZWx0YXMgd2l0aCBsaWdodCBjb2xvcnMgKGUuZy4sIHRoZSBQYXJhbmEsIE5pbGUsIEVicm8sIENvbG9yYWRvLCBCcmFobWFuaSkgaGF2ZSBsb3RzIG9mIGRhdGEsIHNwcmVhZCBvdXQgdGhyb3VnaCB0aGUgbW9udGhzIG9mIHRoZSB5ZWFyLgoKCkknbGwgcmVtb3ZlL3N1YnNldCB0aGUgZGVsdGFzIHdpdGggc3BhcnNlIGNvdmVyYWdlIChzcGVjaWZpY2FsbHksIG1vbnRocyB3aXRoIG5vIGNvdmVyYWdlKS4uLi4gCmBgYHtyfQoKIyBuZWVkIDEwIGRhdGEgcG9pbnRzIHBlciBtb250aCBmb3IgTkRTU0kgYW5kIE5EVkkKRW5vdWdoT2JzUGVyTW9udGggPC0gRGVsdGFzQ2xlYW4gJT4lIHVuZ3JvdXAoKSAlPiUKICBjb3VudChEZWx0YSwgbW9udGgsIHN1cmZhY2UpICU+JSAKICBncm91cF9ieShzdXJmYWNlKSAlPiUKICBmaWx0ZXIoIG4gPj0gNSkKCiNmaW5kIGRlbHRhcyBtaXNzaW5nIGEgZ2l2ZW4gbW9udGggb2Ygb2JzZXJ2YXRpb25zCkRlbHRhTW9udGhDb3VudHMgPC0gRW5vdWdoT2JzUGVyTW9udGggJT4lCiAgdW5ncm91cCgpICU+JQogIGNvdW50KERlbHRhKQoKIyBuZWVkIDEyIG1vbnRocyBvZiB3YXRlciBhbmQgbGFuZCBvYnMsIHNvIDI0IG1vIHRvdGFsCkVub3VnaE1vbnRocyA8LSBEZWx0YU1vbnRoQ291bnRzICU+JQogZmlsdGVyKCBuID09IDI0KQoKQ29tcGxldGVPYnNEZWx0YXMgPC0gcHVsbChFbm91Z2hNb250aHMsIERlbHRhKQoKI3JlbW92ZSB0aGVtCkRlbHRhc0NsZWFuZXIgPC0gRGVsdGFzQ2xlYW4gJT4lCiAgZmlsdGVyKERlbHRhICVpbiUgQ29tcGxldGVPYnNEZWx0YXMpCgojYWRkIHRoZSByZWFsIGRhdGVzIGluIG1vbnRoIGRhdGUgZm9ybWF0CkRlbHRhc0NsZWFuZXIkZGF0ZSA8LSBhcy5EYXRlKHBhc3RlKERlbHRhc0NsZWFuZXIkeWVhciwgRGVsdGFzQ2xlYW5lciRtb250aCwgIjAxIiwgc2VwPSItIiksICIlWS0lbS0lZCIpCgojcmVtb3ZlIGludGVybWVkaWF0ZSBkYXRhCnJtKENvbXBsZXRlT2JzRGVsdGFzLCBFbm91Z2hNb250aHMsIERlbHRhTW9udGhDb3VudHMpCgojRW5vdWdoTW9udGhzCmBgYAoKYW5kIGV4dHJhY3Qgc29tZSBtZXRyaWNzOyBzcGVjaWZpY2FsbHkgSSB3aWxsIG1ha2UgYSB0aW1lc2VyaWVzIG9mIE5EVkkgYW5kIE5EU1NJIGZvciBlYWNoIGRlbHRhIHVzaW5nIHRoZSBtZWFuIHZhbHVlIGZvciBlYWNoIG1vbnRoLgoKYGBge3IgIGluY2x1ZGUgPSBUUlVFfQojdGFrZSB0aGUgbWVhbiBORFZJIGFuZCBORFNTSSBmb3IgZWFjaCBtb250aCwgZm9yIGVhY2ggZGVsdGEKRGVsdGFNZWFucyA8LSBEZWx0YXNDbGVhbmVyICU+JQogIGdyb3VwX2J5KERlbHRhLCBtb250aCwgc3VyZmFjZSkgJT4lCiAgc3VtbWFyaXplKE1lYW5ORFZJID0gbWVhbihuZHZpLCBuYS5ybSA9IFRSVUUpLCBNZWFuTkRTU0kgPSBtZWFuKG5kc3NpLCBuYS5ybSA9IFRSVUUpKQoKI21ha2UgYSA5IGNvbHVtbiBkYXRhIGZyYW1lIHdpdGg6CiNkZWx0YSwgCiNtYXggYW5kIG1pbiBORFZJIG1vbnRoLCAKI05EU1NJIG1heCBhbmQgbWluIG1vbnRoLCAKI21heCBhbmQgbWluIHZhbHVlcyBmb3IgYm90aCBORFZJIGFuZCBORFNTSQoKIyMjIyMKCkRlbHRhTWF4TkRWSSA8LSAKICBEZWx0YU1lYW5zICU+JSAKICBmaWx0ZXIoc3VyZmFjZSA9PSAnTGFuZCcpICAlPiUgCiAgc2VsZWN0ICgtYyhNZWFuTkRTU0kpKSAlPiUgCiAgZ3JvdXBfYnkoRGVsdGEpICU+JSAKICBzbGljZSh3aGljaC5tYXgoTWVhbk5EVkkpKSAlPiUgCiAgcmVuYW1lKE1heE1lYW5ORFZJbW9udGggPSBtb250aCwgTWF4TWVhbk5EVkkgPSBNZWFuTkRWSSkKCkRlbHRhTWF4TkRTU0kgPC0gCiAgRGVsdGFNZWFucyAlPiUgCiAgZmlsdGVyKHN1cmZhY2UgPT0gJ1dhdGVyJykgICU+JSAKICBzZWxlY3QgKC1jKE1lYW5ORFZJKSkgJT4lIAogIGdyb3VwX2J5KERlbHRhKSAlPiUgCiAgc2xpY2Uod2hpY2gubWF4KE1lYW5ORFNTSSkpICU+JSAKICByZW5hbWUoTWF4TWVhbk5EU1NJbW9udGggPSBtb250aCwgTWF4TWVhbk5EU1NJID0gTWVhbk5EU1NJKQoKRGVsdGFNaW5ORFZJIDwtIAogIERlbHRhTWVhbnMgJT4lIAogIGZpbHRlcihzdXJmYWNlID09ICdMYW5kJykgICU+JSAKICBzZWxlY3QgKC1jKE1lYW5ORFNTSSkpICU+JSAKICBncm91cF9ieShEZWx0YSkgJT4lIAogIHNsaWNlKHdoaWNoLm1pbihNZWFuTkRWSSkpICU+JSAKICByZW5hbWUoTWluTWVhbk5EVkltb250aCA9IG1vbnRoLCBNaW5NZWFuTkRWSSA9IE1lYW5ORFZJKQoKRGVsdGFNaW5ORFNTSSA8LSAKICBEZWx0YU1lYW5zICU+JSAKICBmaWx0ZXIoc3VyZmFjZSA9PSAnV2F0ZXInKSAgJT4lIAogIHNlbGVjdCAoLWMoTWVhbk5EVkkpKSAlPiUgCiAgZ3JvdXBfYnkoRGVsdGEpICU+JSAKICBzbGljZSh3aGljaC5taW4oTWVhbk5EU1NJKSkgJT4lIAogIHJlbmFtZShNaW5NZWFuTkRTU0ltb250aCA9IG1vbnRoLCBNaW5NZWFuTkRTU0kgPSBNZWFuTkRTU0kpCgoKI2pvaW4gaW50byAxIGRhdGFmcmFtZQpEZWx0YU1heE1pbiA8LSBsZWZ0X2pvaW4oRGVsdGFNYXhORFZJLCBEZWx0YU1heE5EU1NJLCBieSA9ICdEZWx0YScpICU+JSAKICBsZWZ0X2pvaW4oLixEZWx0YU1pbk5EVkksIGJ5ID0gJ0RlbHRhJykgJT4lIAogIGxlZnRfam9pbiguLERlbHRhTWluTkRTU0ksIGJ5ID0gJ0RlbHRhJykKCiNyZW1vdmUgaW50ZXJtZWRpYXRlIGRhdGEKcm0oRGVsdGFNYXhORFZJLCBEZWx0YU1heE5EU1NJLCBEZWx0YU1pbk5EU1NJLERlbHRhTWluTkRWSSkKCmBgYAoKCkFuZCBub3cgd2UgY2FuIGxvb2sgYXQgdGhlIHBoYXNlIHNoaWZ0cyBiZXR3ZWVuIHRoZXNlIHR3byB0aW1lIHNlcmllcyAodGhlIHRpbWVzZXJpZXMgb2YgbWVhbiBORFZJIGFuZCBtZWFuIE5EU1NJKS4gSGVyZSBhcmUgdGhlIHBoYXNlIHNoaWZ0cyAoaW4gbW9udGgpIGZvciBlYWNoIGRlbHRhOgpgYGB7ciB9CiNjb21wYXJlIG9mZnNldApEZWx0YU1heE1pbiA8LSBtdXRhdGUoRGVsdGFNYXhNaW4sIAogICAgICAgICAgICAgICAgICAgICAgTWluT2Zmc2V0ID0gaWZfZWxzZShhYnMoTWluTWVhbk5EVkltb250aCAtIE1pbk1lYW5ORFNTSW1vbnRoKSA+IDYsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxMiAtIGFicyhNaW5NZWFuTkRWSW1vbnRoIC0gTWluTWVhbk5EU1NJbW9udGgpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhYnMoTWluTWVhbk5EVkltb250aCAtIE1pbk1lYW5ORFNTSW1vbnRoKSksCiAgICAgICAgICAgICAgICAgICAgICBNYXhPZmZzZXQgPSBpZl9lbHNlKGFicyhNYXhNZWFuTkRWSW1vbnRoIC0gTWF4TWVhbk5EU1NJbW9udGgpID4gNiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMTIgLSBhYnMoTWF4TWVhbk5EVkltb250aCAtIE1heE1lYW5ORFNTSW1vbnRoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWJzKE1heE1lYW5ORFZJbW9udGggLSBNYXhNZWFuTkRTU0ltb250aCkpLAogICAgICAgICAgICAgICAgICAgICAgT2Zmc2V0RGlmZiA9IGFicyhNYXhPZmZzZXQgLSBNaW5PZmZzZXQpLAogICAgICAgICAgICAgICAgICAgICAgcmFuZ2VORFZJID0gKE1heE1lYW5ORFZJIC0gTWluTWVhbk5EVkkpLCAKICAgICAgICAgICAgICAgICAgICAgIHJhbmdlTkRTU0kgPSAoTWF4TWVhbk5EU1NJIC0gTWluTWVhbk5EU1NJKSwKICAgICAgICAgICAgICAgICAgICAgIGhhbGZQZXJpb2RORFZJID0gaWZfZWxzZShhYnMoTWF4TWVhbk5EVkltb250aCAtIE1pbk1lYW5ORFZJbW9udGgpID4gNiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEyIC0gYWJzKE1heE1lYW5ORFZJbW9udGggLSBNaW5NZWFuTkRWSW1vbnRoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWJzKE1heE1lYW5ORFZJbW9udGggLSBNaW5NZWFuTkRWSW1vbnRoKSksCiAgICAgICAgICAgICAgICAgICAgICBoYWxmUGVyaW9kTkRTU0kgPSBpZl9lbHNlKGFicyhNYXhNZWFuTkRTU0ltb250aCAtIE1pbk1lYW5ORFNTSW1vbnRoKSA+IDYsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxMiAtIGFicyhNYXhNZWFuTkRTU0ltb250aCAtIE1pbk1lYW5ORFNTSW1vbnRoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWJzKE1heE1lYW5ORFNTSW1vbnRoIC0gTWluTWVhbk5EU1NJbW9udGgpKSwgKQoKIyBEZWx0YU1heE1pbiA8LSAKIyAgIERlbHRhTWF4TWluICAgJT4lCiMgICBzZWxlY3QgKGMoRGVsdGEsIE1pbk9mZnNldCwgTWF4T2Zmc2V0LCBPZmZzZXREaWZmLCByYW5nZU5EVkksIHJhbmdlTkRTU0ksTWF4TWVhbk5EU1NJLE1pbk1lYW5ORFNTSSxNYXhNZWFuTkRWSSxNaW5NZWFuTkRWSSkpIAoKRGVsdGFNYXhNaW4KCmdncGxvdChEZWx0YU1heE1pbiwgYWVzKHkgPSBEZWx0YSwgeCA9IE1heE9mZnNldCkpICsgZ2VvbV9wb2ludCgpICsgCiAgc2NhbGVfeF9kaXNjcmV0ZShsaW1pdHMgPSBjKDE6NiksIGJyZWFrcyA9IGMoMTo2KSkgKwogIGV4cGFuZF9saW1pdHMoeCA9IGMoMCw2KSkgICsgCiAgZ2d0aXRsZSgiTWF4T2Zmc2V0IikKCmdncGxvdChEZWx0YU1heE1pbiwgYWVzKHkgPSBEZWx0YSwgeCA9IE1pbk9mZnNldCkpICsgZ2VvbV9wb2ludCgpICsgCiAgc2NhbGVfeF9kaXNjcmV0ZShsaW1pdHMgPSBjKDE6NiksIGJyZWFrcyA9IGMoMTo2KSkgKwogIGV4cGFuZF9saW1pdHMoeCA9IGMoMCw2KSkgICsgCiAgZ2d0aXRsZSgiTWluT2Zmc2V0IikKCmdncGxvdChEZWx0YU1heE1pbiwgYWVzKHkgPSBEZWx0YSwgeCA9IE9mZnNldERpZmYpKSArIGdlb21fcG9pbnQoKSArIAogIHNjYWxlX3hfZGlzY3JldGUobGltaXRzID0gYygxOjYpLCBicmVha3MgPSBjKDE6NikpICsKICBleHBhbmRfbGltaXRzKHggPSBjKDAsNikpICArIAogIGdndGl0bGUoIk9mZnNldCBEaWZmZXJlbmNlIikKCmBgYAoKTm93IGxldCdzIGV4YW1pbmUgdGhlIGhpc3RvZ3JhbXMgb2YgYWxsIDMxIGRlbHRhcy4uLiBUaGUgbW9udGhzIHdpdGggdGhlIGdyZWF0ZXN0IG1lYW4gTkRWSSwgbW9udGhzIHdpdGggZ3JldGFlc3QgbWVhbiBORFNTSSwgdGhlIG1vbnRobHkgb2Zmc2V0LCBhbmQgdGhlIHNrZXcgb2YgdGhlIE5EU1NJIGFuZCBORFZJIHRpbWVzZXJpZXMuCgpgYGB7cn0KZ2dwbG90KERlbHRhTWF4TWluLCBhZXMoeCA9IE1heE1lYW5ORFZJbW9udGgpKSArIAogIGdlb21fZG90cGxvdChiaW53aWR0aCA9IDEsZG90c2l6ZSA9IDAuNSkgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMoTlVMTCwgYnJlYWtzID0gTlVMTCkgKyAKICBzY2FsZV94X2Rpc2NyZXRlKGxpbWl0cyA9IGMoMToxMiksIGJyZWFrcyA9IGMoMToxMikpICsgCiAgbGFicyh4ID0gIk1vbnRoIikgKwogIGdndGl0bGUoIk1vbnRoIG9mIG1heGltdW0gbWVhbiBORFZJIikKCmdncGxvdChEZWx0YU1heE1pbiwgYWVzKHggPSBNYXhNZWFuTkRTU0ltb250aCkpICsgCiAgZ2VvbV9kb3RwbG90KGJpbndpZHRoID0gMSxkb3RzaXplID0gMC41KSArIAogIHNjYWxlX3lfY29udGludW91cyhOVUxMLCBicmVha3MgPSBOVUxMKSArIAogIHNjYWxlX3hfZGlzY3JldGUobGltaXRzID0gYygxOjEyKSwgYnJlYWtzID0gYygxOjEyKSkgKyAKICBsYWJzKHggPSAiTW9udGgiKSArCiAgZ2d0aXRsZSgiTW9udGggb2YgbWF4aW11bSBtZWFuIE5EU1NJIikKCmdncGxvdChEZWx0YU1heE1pbiwgYWVzKHggPSBNYXhPZmZzZXQpKSArIAogIGdlb21fZG90cGxvdChiaW53aWR0aCA9IDEsZG90c2l6ZSA9IDAuMjUpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKE5VTEwsIGJyZWFrcyA9IE5VTEwpICsgCiAgc2NhbGVfeF9kaXNjcmV0ZShsaW1pdHMgPSBjKDA6NiksIGJyZWFrcyA9IGMoMDo2KSkgKyAKICBsYWJzKHggPSAiTW9udGhzIikgKwogIGdndGl0bGUoIk1vbnRocyBPZmZzZXQgYmV0d2VlbiBORFZJIGFuZCBORFNTSSIpCgpnZ3Bsb3QoRGVsdGFNYXhNaW4sIGFlcyh4ID0gaGFsZlBlcmlvZE5EVkkpKSArIAogIGdlb21fZG90cGxvdChiaW53aWR0aCA9IDEsZG90c2l6ZSA9IDAuMjUpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKE5VTEwsIGJyZWFrcyA9IE5VTEwpICsgCiAgc2NhbGVfeF9kaXNjcmV0ZShsaW1pdHMgPSBjKDA6NiksIGJyZWFrcyA9IGMoMDo2KSkgKyAKICBsYWJzKHggPSAiTW9udGhzIikgKwogIGdndGl0bGUoImhhbGYgcGVyaW9kIE5EVkkgIikKCmdncGxvdChEZWx0YU1heE1pbiwgYWVzKHggPSBoYWxmUGVyaW9kTkRTU0kpKSArIAogIGdlb21fZG90cGxvdChiaW53aWR0aCA9IDEsZG90c2l6ZSA9IDAuMjUpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKE5VTEwsIGJyZWFrcyA9IE5VTEwpICsgCiAgc2NhbGVfeF9kaXNjcmV0ZShsaW1pdHMgPSBjKDA6NiksIGJyZWFrcyA9IGMoMDo2KSkgKyAKICBsYWJzKHggPSAiTW9udGhzIikgKwogIGdndGl0bGUoImhhbGYgcGVyaW9kIE5EU1NJIikKCmBgYAoKT2ssIHNvIHRoZSBpZGVhIGlzIHRoYXQgcGVhayBORFNTSSBpcyBtb3JlIGVmZmVjdGl2ZSBpZiBpdCBvY2N1cnMgYXQgbW9kZXJhdGUgTkRWSSwgc28gbGV0J3MgbG9vayBhdCB0aGUgTkRWSSB2YWx1ZSBmb3IgdGhlIG1vbnRocyB3aXRoIHBlYWsgTkRTU0kuIApgYGB7cn0KI2V4dHJhY3QgTkRWSSB2YWx1ZSBmb3IgZWFjaCBkZWx0YSBhIHRoZSBtb250aCBvZiBtYXggTkRTU0kgdmFsdWUKCkRlbHRhTkRWSWF0TWF4TkRTU0kgPC0gRGVsdGFNYXhNaW4gJT4lCiAgc2VsZWN0KERlbHRhLE1heE1lYW5ORFNTSW1vbnRoKQoKRGVsdGFNZWFuc1RvSm9pbiA8LSBEZWx0YU1lYW5zICU+JQogIGZpbHRlcihzdXJmYWNlID09ICdMYW5kJykKCkRlbHRhTkRWSWF0TWF4TkRTU0kgPC0gbGVmdF9qb2luKERlbHRhTkRWSWF0TWF4TkRTU0ksIERlbHRhTWVhbnNUb0pvaW4sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGMoJ0RlbHRhJywgJ01heE1lYW5ORFNTSW1vbnRoJyA9J21vbnRoJykpCiAKRGVsdGFORFZJYXRNYXhORFNTSSA8LSBEZWx0YU5EVklhdE1heE5EU1NJICU+JQogIHNlbGVjdCAoLWMoc3VyZmFjZSwgTWVhbk5EU1NJKSkKCkRlbHRhTkRWSWF0TWF4TkRTU0kKCmdncGxvdChEZWx0YU5EVklhdE1heE5EU1NJLCBhZXMoeCA9IE1lYW5ORFZJKSkgKyAKICBnZW9tX2RvdHBsb3QoYmlud2lkdGggPSAwLjEsIGRvdHNpemUgPSAwLjI1KSArIAogIHNjYWxlX3lfY29udGludW91cyhOVUxMLCBicmVha3MgPSBOVUxMKSAgKyAKICB4bGltKDAsMSkgKwogIGxhYnMoeCA9ICJORFZJIikgKwogIGdndGl0bGUoIk5EVkkgYXQgbW9udGggb2YgbWF4aW11bSBtZWFuIE5EU1NJIikKYGBgCgpIb3cgYWJvdXQgdGhlIE5EVkkgZm9yIG1vbnRocyB3aXRoIHRoZSBsb3dlc3QgTkRTU0kKCmBgYHtyfQojZXh0cmFjdCBORFZJIHZhbHVlIGZvciBlYWNoIGRlbHRhIGEgdGhlIG1vbnRoIG9mIG1pbiBORFNTSSB2YWx1ZQoKRGVsdGFORFZJYXRNaW5ORFNTSSA8LSBEZWx0YU1heE1pbiAlPiUKICBzZWxlY3QoRGVsdGEsTWluTWVhbk5EU1NJbW9udGgpCgpEZWx0YU1lYW5zVG9Kb2luIDwtIERlbHRhTWVhbnMgJT4lCiAgZmlsdGVyKHN1cmZhY2UgPT0gJ0xhbmQnKQoKRGVsdGFORFZJYXRNaW5ORFNTSSA8LSBsZWZ0X2pvaW4oRGVsdGFORFZJYXRNaW5ORFNTSSwgRGVsdGFNZWFuc1RvSm9pbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gYygnRGVsdGEnLCAnTWluTWVhbk5EU1NJbW9udGgnID0nbW9udGgnKSkKIApEZWx0YU5EVklhdE1pbk5EU1NJIDwtIERlbHRhTkRWSWF0TWluTkRTU0kgJT4lCiAgc2VsZWN0ICgtYyhzdXJmYWNlLCBNZWFuTkRTU0kpKQoKRGVsdGFORFZJYXRNYXhORFNTSQoKZ2dwbG90KERlbHRhTkRWSWF0TWluTkRTU0ksIGFlcyh4ID0gTWVhbk5EVkkpKSArIAogIGdlb21fZG90cGxvdChiaW53aWR0aCA9IDAuMSwgZG90c2l6ZSA9IDAuMjUpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKE5VTEwsIGJyZWFrcyA9IE5VTEwpICArIAogIHhsaW0oMCwxKSArCiAgbGFicyh4ID0gIk5EVkkiKSArCiAgZ2d0aXRsZSgiTkRWSSBhdCBtb250aCBvZiBtaW4gbWVhbiBORFNTSSIpCmBgYAoKSnVzdCB0byBleHBsb3JlIHRoZSBkYXRhIGEgYml0LCBoZXJlIGFyZSB0aGUgcGhhc2Ugc2hpZnRzL29mZnNldHMgYWdhaW5zdCBvdGhlciBtZWFzdXJlZCBwYXJhbWV0ZXJzIGZvciBlYWNoIGRlbHRhLiBUaGUgcmFuZ2UsIG1heCBhbmQgbWVhbiBvZiBORFZJIGFuZCBORFNTSSBpcyBjYWxjdWxhdGVkIGZyb20gdGhlIHRpbWVzZXJpZXMsIHNvIGl0IGlzIHJlYWxseSB0aGUgbWF4LCBtaW4sIGFuZCByYW5nZSBvZiB0aGUgbW9udGhseSBtZWFucyAoaS5lLiwgdGhlIG1heGltdW0gb2YgdGhlIG1lYW5zLCB0aGUgbWluaW11bSBvZiB0aGUgbWVhbnMsIGFuZCB0aGUgcmFuZ2Ugb2YgdGhlIG1lYW4pLiBPZmZzZXQgaXMgbWVhc3VyZWQgaW4gbW9udGhzLgoKYGBge3J9CnNsaWNlMSA8LSBnZ3Bsb3QoRGVsdGFNYXhNaW4sIGFlcyh5ID0gcmFuZ2VORFZJLCB4ID0gTWF4T2Zmc2V0KSkgKyBnZW9tX3BvaW50KCkgCiMgKyBzY2FsZV94X2Rpc2NyZXRlKGxpbWl0cyA9IGMoMTo2KSwgYnJlYWtzID0gYygxOjYpKSArIGV4cGFuZF9saW1pdHMoeCA9IGMoMSw2KSkgCgpzbGljZTIgPC0gZ2dwbG90KERlbHRhTWF4TWluLCBhZXMoeSA9IHJhbmdlTkRWSSwgeCA9IHJhbmdlTkRTU0kpKSArIGdlb21fcG9pbnQoKSAKc2xpY2UzIDwtIGdncGxvdChEZWx0YU1heE1pbiwgYWVzKHkgPSByYW5nZU5EU1NJLCB4ID0gTWF4T2Zmc2V0KSkgKyBnZW9tX3BvaW50KCkgCgpzbGljZTQgPC0gZ2dwbG90KERlbHRhTWF4TWluLCBhZXMoeSA9IE1heE1lYW5ORFZJLCB4ID0gcmFuZ2VORFZJKSkgKyBnZW9tX3BvaW50KCkgCnNsaWNlNSA8LSBnZ3Bsb3QoRGVsdGFNYXhNaW4sIGFlcyh5ID0gTWF4TWVhbk5EVkksIHggPSByYW5nZU5EU1NJKSkgKyBnZW9tX3BvaW50KCkgCnNsaWNlNiA8LSBnZ3Bsb3QoRGVsdGFNYXhNaW4sIGFlcyh5ID0gTWF4TWVhbk5EVkksIHggPSBNYXhPZmZzZXQpKSArIGdlb21fcG9pbnQoKSAKCnNsaWNlNyA8LSBnZ3Bsb3QoRGVsdGFNYXhNaW4sIGFlcyh5ID0gTWF4TWVhbk5EU1NJLCB4ID0gTWF4TWVhbk5EVkkpKSArIGdlb21fcG9pbnQoKSAKc2xpY2U4IDwtIGdncGxvdChEZWx0YU1heE1pbiwgYWVzKHkgPSBNYXhNZWFuTkRTU0ksIHggPSByYW5nZU5EU1NJKSkgKyBnZW9tX3BvaW50KCkgCnNsaWNlOSA8LSBnZ3Bsb3QoRGVsdGFNYXhNaW4sIGFlcyh5ID0gTWF4TWVhbk5EU1NJLCB4ID0gTWF4T2Zmc2V0KSkgKyBnZW9tX3BvaW50KCkgCnNsaWNlMTAgPC0gZ2dwbG90KERlbHRhTWF4TWluLCBhZXMoeSA9IE1heE1lYW5ORFNTSSwgeCA9IHJhbmdlTkRWSSkpICsgZ2VvbV9wb2ludCgpIAoKZ3JpZC5hcnJhbmdlKHNsaWNlMSwgc2xpY2UyLCBzbGljZTMsIHNsaWNlNCwgc2xpY2U1LCBzbGljZTYsIG5jb2w9MykKZ3JpZC5hcnJhbmdlKHNsaWNlNywgc2xpY2U4LCBzbGljZTksIHNsaWNlMTAsIG5jb2w9MikKCiNyZW1vdmUgdGhvc2UgcGFuZWxzCnJtKHNsaWNlMSwgc2xpY2UyLCBzbGljZTMsIHNsaWNlNCwgc2xpY2U1LCBzbGljZTYsc2xpY2U3LCBzbGljZTgsIHNsaWNlOSwgc2xpY2UxMCkKCmBgYAoKCkpvaW4gTGF0aXR1ZGUgYW5kIGxvbmdpdHVkZSBkYXRhCgpgYGB7cn0KRGVsdGFEYXRhd0xvY2F0aW9ucyA8LSBsZWZ0X2pvaW4oRGVsdGFNYXhNaW4sIERlbHRhTG9jYXRpb25zLCBieSA9IGMoIkRlbHRhIiA9ICJEZWx0YXMiKSkKCkRlbHRhRGF0YXdMb2NhdGlvbnMgPC0gRGVsdGFEYXRhd0xvY2F0aW9ucyAlPiUKICBtdXRhdGUoQWJzb2x1dGVfTGF0aXR1ZGU9IGFicyhMYXQpKQpgYGAKCnBsb3QgcGFyYW1zIHZzIGxhdApgYGB7cn0KbG9jMSA8LSBnZ3Bsb3QoRGVsdGFEYXRhd0xvY2F0aW9ucywgYWVzKHkgPSBBYnNvbHV0ZV9MYXRpdHVkZSwgeCA9IE1heE9mZnNldCkpICsgZ2VvbV9wb2ludCgpIApsb2MyIDwtIGdncGxvdChEZWx0YURhdGF3TG9jYXRpb25zLCBhZXMoeSA9IEFic29sdXRlX0xhdGl0dWRlLCB4ID0gcmFuZ2VORFNTSSkpICsgZ2VvbV9wb2ludCgpIApsb2MzIDwtIGdncGxvdChEZWx0YURhdGF3TG9jYXRpb25zLCBhZXMoeSA9IEFic29sdXRlX0xhdGl0dWRlLCB4ID0gcmFuZ2VORFZJKSkgKyBnZW9tX3BvaW50KCkgCmxvYzQgPC0gZ2dwbG90KERlbHRhRGF0YXdMb2NhdGlvbnMsIGFlcyh5ID0gQWJzb2x1dGVfTGF0aXR1ZGUsIHggPSBNYXhNZWFuTkRWSSkpICsgZ2VvbV9wb2ludCgpIApsb2M1IDwtIGdncGxvdChEZWx0YURhdGF3TG9jYXRpb25zLCBhZXMoeSA9IEFic29sdXRlX0xhdGl0dWRlLCB4ID0gTWF4TWVhbk5EU1NJKSkgKyBnZW9tX3BvaW50KCkgCgpncmlkLmFycmFuZ2UobG9jMSwgbG9jMiwgbG9jMywgbG9jNCwgbG9jNSwgbmNvbD0yKQoKbG9jMQojZ2dzYXZlKCJsb2MxLnBkZiIsIHdpZHRoID0gNCwgaGVpZ2h0ID0gNCkKbG9jMgojZ2dzYXZlKCJsb2MyLnBkZiIsIHdpZHRoID0gNCwgaGVpZ2h0ID0gNCkKbG9jMwojZ2dzYXZlKCJsb2MzLnBkZiIsIHdpZHRoID0gNCwgaGVpZ2h0ID0gNCkKCiNyZW1vdmUgdGhvc2UgcGFuZWxzCnJtKGxvYzEsIGxvYzIsIGxvYzMsIGxvYzQsIGxvYzUpCmBgYAoKYGBge3J9CiNmaW5kIHRoZSBsaW5lYXIgbW9kZWwgCkRlbHRhT2Zmc2V0X2xtIDwtIGxtKCBBYnNvbHV0ZV9MYXRpdHVkZSB+IE1heE9mZnNldCwgZGF0YSA9IERlbHRhRGF0YXdMb2NhdGlvbnMpIAoKc3VtbWFyeShEZWx0YU9mZnNldF9sbSkKCmdncGxvdChEZWx0YURhdGF3TG9jYXRpb25zLCBhZXMoeCA9IEFic29sdXRlX0xhdGl0dWRlLCB5ID0gTWF4T2Zmc2V0KSkgKyAKICBnZW9tX3BvaW50KCkgKwogIGdlb21fc21vb3RoKG1hcHBpbmcgPSBhZXMoeCA9IEFic29sdXRlX0xhdGl0dWRlLCB5ID0gTWF4T2Zmc2V0LCApLCBtZXRob2Q9bG0gKSAKCgoKYGBgCgoKTm93IGZvciBzb21lIG1hcHMgb2YgdGhlIGRhdGEgbWFwczoKCmBgYHtyfQp3b3JsZCA8LSBnZ3Bsb3QoKSArCiAgYm9yZGVycygid29ybGQiLCBjb2xvdXIgPSAiZ3JheTg1IiwgZmlsbCA9ICJncmF5ODAiKSArCiAgdGhlbWVfbWFwKCkgCgpEZWx0YU9mZnNldE1hcCA8LSB3b3JsZCArCiAgZ2VvbV9wb2ludChhZXMoeCA9IExvbiwgeSA9IExhdCwgY29sb3IgPSBNYXhPZmZzZXQpLAogICAgICAgICAgICAgZGF0YSA9IERlbHRhRGF0YXdMb2NhdGlvbnMsIAogICAgICAgICAgICAgc2l6ZSA9IDUpICsgc2NhbGVfY29sb3JfZ3JhZGllbnQoIGhpZ2ggPSAicmVkIiwgbG93ICA9ICJ5ZWxsb3ciKSArCiAgZ2d0aXRsZSgiT2Zmc2V0IEJldHdlZW4gTkRWSSBwZWFrIG9uIExhbmQgYW5kIE5EU1NJIHBlYWsgaW4gd2F0ZXIiKQoKRGVsdGFPZmZzZXRNYXAKI2dnc2F2ZSgiRGVsdGFPZmZzZXRNYXAucGRmIiwgd2lkdGggPSA2LCBoZWlnaHQgPSA0KQoKYGBgCgoKYGBge3J9CndvcmxkIDwtIGdncGxvdCgpICsKICBib3JkZXJzKCJ3b3JsZCIsIGNvbG91ciA9ICJncmF5ODUiLCBmaWxsID0gImdyYXk4MCIpICsKICB0aGVtZV9tYXAoKSAKCkRlbHRhTkRWSXJhbmdlTWFwIDwtIHdvcmxkICsKICBnZW9tX3BvaW50KGFlcyh4ID0gTG9uLCB5ID0gTGF0LCBjb2xvciA9IHJhbmdlTkRWSSksCiAgICAgICAgICAgICBkYXRhID0gRGVsdGFEYXRhd0xvY2F0aW9ucywKICAgICAgICAgICAgIHNpemUgPSA1KSArIHNjYWxlX2NvbG9yX2dyYWRpZW50KCBoaWdoID0gInJlZCIsIGxvdyAgPSAieWVsbG93IikgKyAKICBnZ3RpdGxlKCJORFZJIHJhbmdlIikKCgpEZWx0YU5EU1NJcmFuZ2VNYXAgIDwtIHdvcmxkICsKICBnZW9tX3BvaW50KGFlcyh4ID0gTG9uLCB5ID0gTGF0LCBjb2xvciA9IHJhbmdlTkRTU0kpLAogICAgICAgICAgICAgZGF0YSA9IERlbHRhRGF0YXdMb2NhdGlvbnMsIAogICAgICAgICAgICAgc2l6ZSA9IDUpICsgc2NhbGVfY29sb3JfZ3JhZGllbnQoIGhpZ2ggPSAicmVkIiwgbG93ID0gInllbGxvdyIpICsgZ2d0aXRsZSgiTkRTU0kgcmFuZ2UiKSAKCkRlbHRhTkRWSXJhbmdlTWFwIAojZ2dzYXZlKCJEZWx0YU5EVklyYW5nZU1hcC5wZGYiLCB3aWR0aCA9IDYsIGhlaWdodCA9IDQpCkRlbHRhTkRTU0lyYW5nZU1hcAojZ2dzYXZlKCJEZWx0YU5EU1NJcmFuZ2VNYXAucGRmIiwgd2lkdGggPSA2LCBoZWlnaHQgPSA0KQoKYGBgCgpMZXQncyBsb29rIGF0IHNvbWUgb2YgdGhlIHRpbWVzZXJpZXMgClRvIHF1YW50aWZ5IHRoZSB3YXRlciwgd2UgdXNlIE5EU1NJLiB0byBxdWFudGlmeSBsYW5kLCB3ZSB1c2UgTkRWSS4KCkZpcnN0IGhlcmUgaXMgdGhlIGZ1bmN0aW9uIHRvIG1ha2UgdGhlIHBsb3RzOgoKYGBge3J9CkRlbHRhUGxvdHRlciA8LSBmdW5jdGlvbihEZWx0YU5hbWUpIHsKICAjQ291bnRzIGVhY2ggbW9udGgKICBudW1WZWcgPC0gRGVsdGFzQ2xlYW5lciAlPiUKICAgIHNlbGVjdChEZWx0YSwgc3VyZmFjZSwgbW9udGgsIG5kdmkpICU+JQogICAgZmlsdGVyKERlbHRhID09IERlbHRhTmFtZSAmIHN1cmZhY2UgPT0gIkxhbmQiICYgIWlzLm5hKG5kdmkpKSAlPiUKICAgIGdyb3VwX2J5KG1vbnRoKSAlPiUKICAgIHN1bW1hcml6ZShuID0gbigpKQogIAogIG51bVNlZCA8LSBEZWx0YXNDbGVhbmVyICU+JQogICAgc2VsZWN0KERlbHRhLCBzdXJmYWNlLCBtb250aCwgbmRzc2kpICU+JQogICAgZmlsdGVyKERlbHRhID09IERlbHRhTmFtZSAmCiAgICAgICAgICAgICBzdXJmYWNlID09ICJXYXRlciIgJiAhaXMubmEobmRzc2kpKSAlPiUKICAgIGdyb3VwX2J5KG1vbnRoKSAlPiUKICAgIHN1bW1hcml6ZShuID0gbigpKQogIAogICNIaWdobGlnaHQgdGhlIE1heGltdW0gYW5kIE1pbmltdW0gTW9udGggZm9yIGVhY2ggZGVsdGEsIE5EVkkgYW5kIE5EU1NJCiAgCiAgI0xBTkQKICBWZWcgPC0KICAgIGdncGxvdChkYXRhID0gZmlsdGVyKERlbHRhc0NsZWFuZXIsIERlbHRhID09IERlbHRhTmFtZSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1cmZhY2UgPT0gIkxhbmQiKSkgKwogICAgZ2VvbV9ib3hwbG90KGFlcyh4ID0gbW9udGgsIHkgPSBuZHZpLCBncm91cCA9IG1vbnRoKSkgKwogICAgc2NhbGVfeF9kaXNjcmV0ZShsaW1pdHMgPSBjKDE6MTIpLCBicmVha3MgPSBjKDE6MTIpKSArCiAgICBleHBhbmRfbGltaXRzKHggPSBjKDEsIDEyKSkgKwogICAgZ2d0aXRsZShEZWx0YU5hbWUpICsKICAgICNnZW9tX3RleHQoZGF0YSA9IG51bVZlZywgYWVzKHkgPSAxLjA1LCB4ID0gbW9udGgsIGxhYmVsID0gbikpICsKICAgIGdlb21fYm94cGxvdCgKICAgICAgZGF0YSA9IGZpbHRlcigKICAgICAgICBEZWx0YXNDbGVhbmVyLAogICAgICAgIERlbHRhID09IERlbHRhTmFtZSAmCiAgICAgICAgICBzdXJmYWNlID09ICJMYW5kIiAmIG1vbnRoID09IERlbHRhTWF4TWluJE1heE1lYW5ORFZJbW9udGhbRGVsdGFNYXhNaW4kRGVsdGEgPT0gRGVsdGFOYW1lXSAKICAgICAgKSwKICAgICAgYWVzKHggPSBtb250aCwgeSA9IG5kdmksIGdyb3VwID0gbW9udGgpLAogICAgICBmaWxsID0gImdyZWVuIgogICAgKSArCiAgICBnZW9tX2JveHBsb3QoCiAgICAgIGRhdGEgPSBmaWx0ZXIoCiAgICAgICAgRGVsdGFzQ2xlYW5lciwKICAgICAgICBEZWx0YSA9PSBEZWx0YU5hbWUgJiAKICAgICAgICAgIHN1cmZhY2UgPT0gIkxhbmQiICYgbW9udGggPT0gRGVsdGFNYXhNaW4kTWluTWVhbk5EVkltb250aFtEZWx0YU1heE1pbiREZWx0YSA9PURlbHRhTmFtZV0KICAgICAgKSwKICAgICAgYWVzKHggPSBtb250aCwgeSA9IG5kdmksIGdyb3VwID0gbW9udGgpLAogICAgICBmaWxsID0gImJsdWUiCiAgICApCiAgCiAgCiAgU2VkIDwtCiAgICBnZ3Bsb3QoZGF0YSA9IGZpbHRlcihEZWx0YXNDbGVhbmVyLCBEZWx0YSA9PSBEZWx0YU5hbWUgJgogICAgICAgICAgICAgICAgICAgICAgICAgICBzdXJmYWNlID09ICJXYXRlciIpKSArCiAgICBnZW9tX2JveHBsb3QoYWVzKHggPSBtb250aCwgeSA9IG5kc3NpLCBncm91cCA9IG1vbnRoKSkgKwogICAgc2NhbGVfeF9kaXNjcmV0ZShsaW1pdHMgPSBjKDE6MTIpLCBicmVha3MgPSBjKDE6MTIpKSArCiAgICBleHBhbmRfbGltaXRzKHggPSBjKDEsIDEyKSkgKwogICAgI2dlb21fdGV4dChkYXRhID0gbnVtU2VkLCBhZXMoeSA9IDEuMDUsIHggPSBtb250aCwgbGFiZWwgPSBuKSkgKwogICAgZ2VvbV9ib3hwbG90KAogICAgICBkYXRhID0gZmlsdGVyKAogICAgICAgIERlbHRhc0NsZWFuZXIsCiAgICAgICAgRGVsdGEgPT0gRGVsdGFOYW1lICYKICAgICAgICAgIHN1cmZhY2UgPT0gIldhdGVyIiAmIG1vbnRoID09IERlbHRhTWF4TWluJE1heE1lYW5ORFNTSW1vbnRoW0RlbHRhTWF4TWluJERlbHRhID09IERlbHRhTmFtZV0KICAgICAgKSwKICAgICAgYWVzKHggPSBtb250aCwgeSA9IG5kc3NpLCBncm91cCA9IG1vbnRoKSwKICAgICAgZmlsbCA9ICJncmVlbiIKICAgICkgKwogICAgZ2VvbV9ib3hwbG90KAogICAgICBkYXRhID0gZmlsdGVyKAogICAgICAgIERlbHRhc0NsZWFuZXIsCiAgICAgICAgRGVsdGEgPT0gRGVsdGFOYW1lICYKICAgICAgICAgIHN1cmZhY2UgPT0gIldhdGVyIiAmIG1vbnRoID09IERlbHRhTWF4TWluJE1pbk1lYW5ORFNTSW1vbnRoW0RlbHRhTWF4TWluJERlbHRhID09IERlbHRhTmFtZV0KICAgICAgKSwKICAgICAgYWVzKHggPSBtb250aCwgeSA9IG5kc3NpLCBncm91cCA9IG1vbnRoKSwKICAgICAgZmlsbCA9ICJibHVlIgogICAgKQogIAogIHJldHVybihncmlkLmFycmFuZ2UoVmVnLCBTZWQsIG5yb3cgPSAyKSkKfQpgYGAKCgpIZXJlIGlzIGFyZSBzb21lIGV4YW1wbGVzOgoKKiBUaGUgcGVha3MgaW4gYm90aCB0aW1lc2VyaWVzIHNoaWZ0IGFyb3VuZCBkZXBlbmRpbmcgb24gdGhlIGRlbHRhOgogICArIGxvb2sgYXQgdGhlIGNvcnJlbGF0aW9uIGluIHRoZSBPcmlub2NvIG5hZCBTZW5lZ2FsCiAgICsgVGhlIGFudGljb3JyZWxhdGlvbiBpbiB0aGUgUGFyYW5hIGFuZCBFYnJvLAogICArIFRoZSBzbGlnaHQgcGhhc2Ugc2hpZnQgaW4gdGhlIE1hZ2RhbGVuYS4KCmBgYHtyfQpEZWx0YVBsb3R0ZXIoIlBhcmFuYSIpCkRlbHRhUGxvdHRlcigiTWFnZGFsZW5hIikKRGVsdGFQbG90dGVyKCJFYnJvIikKRGVsdGFQbG90dGVyKCJOaWxlIikKRGVsdGFQbG90dGVyKCJTZW5lZ2FsIikKRGVsdGFQbG90dGVyKCJPcmlub2NvIikKRGVsdGFQbG90dGVyKCJHb2RhdmFyaSIpCkRlbHRhUGxvdHRlcigiS3Jpc2huYSIpCmBgYAoKCk5vdyBmb3Igc29tZSB3b3JrIHdpdGggR1JEQyBkaXNjaGFyZ2UgZGF0YToKYGBge3J9CiNpbXBvcnQgdGhlIGRhdGEgKG1vbnRobHkgbWVhbnMgZm9yIDIxIHN0YXRpb25zKQpEZWx0YXNHUkRDICA8LSByZWFkX2NzdigiLi4vZGF0YS9HUkRDc3RhdGlvbnMuY3N2IikKCiNjYWxjdWxhdGUgdGhlIG1lYW4gb2YgdGhlIG1vbnRobHkgbWVhbnMKRGVsdGFzR1JEQ3dNZWFuIDwtIERlbHRhc0dSREMgJT4lIAogICAgcm93d2lzZSgpICU+JSAKICAgIG11dGF0ZShNTUQ9bWVhbihjKEphbnVhcnksRmVicnVhcnksTWFyY2gsQXByaWwsCiAgICAgICAgICAgICAgICAgICAgTWF5LEp1bmUsSnVseSxBdWd1c3QsCiAgICAgICAgICAgICAgICAgICAgU2VwdGVtYmVyLE9jdG9iZXIsTm92ZW1iZXIsRGVjZW1iZXIpKSkKCkRlbHRhc0dSREN3TWVhbiA8LSBEZWx0YXNHUkRDd01lYW4gJT4lIAogIHJvd3dpc2UoKSAlPiUgCiAgbXV0YXRlKFJhbmdlX0Rpc2NoYXJnZSA9IG1heChjKEphbnVhcnksRmVicnVhcnksTWFyY2gsQXByaWwsCiAgICAgICAgICAgICAgTWF5LEp1bmUsSnVseSxBdWd1c3QsCiAgICAgICAgICAgICAgU2VwdGVtYmVyLE9jdG9iZXIsTm92ZW1iZXIsRGVjZW1iZXIpKSAtIAogICAgICAgICAgIG1pbihjKEphbnVhcnksRmVicnVhcnksTWFyY2gsQXByaWwsCiAgICAgICAgICAgICAgTWF5LEp1bmUsSnVseSxBdWd1c3QsCiAgICAgICAgICAgICAgU2VwdGVtYmVyLE9jdG9iZXIsTm92ZW1iZXIsRGVjZW1iZXIpKQogICAgICAgICAgICkKICAgICAgICAKCiNqb2luIHRvIGxvY2F0aW9uIGRhdGE6CkRlbHRhd0xvY0dSREMgPC0gbGVmdF9qb2luKERlbHRhRGF0YXdMb2NhdGlvbnMsIERlbHRhc0dSREN3TWVhbiwgYnkgPSBjKCJEZWx0YSIgPSAiRGVsdGFzIikpCgoKI3Bsb3QgbWVhbiBvZiBtb250aGx5IG1lYW5zIGFnYWluc3QgTkRTU0kKZ2dwbG90KERlbHRhd0xvY0dSREMsIGFlcyh5ID0gUmFuZ2VfRGlzY2hhcmdlLCB4ID0gcmFuZ2VORFNTSSkpICsgZ2VvbV9wb2ludCgpICsgc2NhbGVfeV9jb250aW51b3VzKHRyYW5zPSdsb2cxMCcpCgojZ2dzYXZlKCJHUkRDTkRTU0kucGRmIiwgd2lkdGggPSA2LCBoZWlnaHQgPSA0KQoKZ2dwbG90KERlbHRhd0xvY0dSREMsIGFlcyh5ID0gUmFuZ2VfRGlzY2hhcmdlLCB4ID0gTWF4TWVhbk5EU1NJKSkgKyBnZW9tX3BvaW50KCkgKyBzY2FsZV95X2NvbnRpbnVvdXModHJhbnM9J2xvZzEwJykKYGBgCgoKYGBge3J9CiNyZW5hbWUgdGhlIG1vbnRocyBieSBudW1iZXJzIGFuZCB0aWR5IHRoZSBHUkRDIGRhdGEKRGVsdGFzRGlzY2hhcmdlIDwtIERlbHRhc0dSREMgJT4lCiAgcmVuYW1lKERlbHRhID0gRGVsdGFzLCIxIiA9IEphbnVhcnksICIyIj0gRmVicnVhcnksICIzIj0gTWFyY2gsICI0Ij0gQXByaWwsCiAgICAgICAgICI1Ij1NYXksICI2Ij1KdW5lLCAiNyI9SnVseSwgIjgiPSBBdWd1c3QsICI5IiA9IFNlcHRlbWJlciwgIjEwIj1PY3RvYmVyLCAKICAgICAgICAgIjExIj1Ob3ZlbWJlciwgIjEyIj1EZWNlbWJlcikgJT4lCiAgc2VsZWN0KERlbHRhLCAiMSIgLCAiMiIgLCAiMyIsICI0IiwiNSIsICI2IiwgIjciLCAiOCIsICI5IiwgIjEwIiwgIjExIiwgIjEyIikgJT4lCiAgcGl2b3RfbG9uZ2VyKC1EZWx0YSwgbmFtZXNfdG8gPSAibW9udGgiLCB2YWx1ZXNfdG8gPSAiZGlzY2hhcmdlIikKCiNmaW5kIG1heCBHUkRDIG1vbnRoIGZvciBlYWNoIGRlbHRhCkRlbHRhTWF4RGlzY2hhcmdlIDwtIAogIERlbHRhc0Rpc2NoYXJnZSAlPiUgCiAgZ3JvdXBfYnkoRGVsdGEpICU+JSAKICBzbGljZSh3aGljaC5tYXgoZGlzY2hhcmdlKSkgJT4lIAogIHJlbmFtZShNYXhEaXNjaGFyZ2VNb250aCA9IG1vbnRoLCBNYXhEaXNjaGFyZ2UgPSBkaXNjaGFyZ2UpIAoKCkRlbHRhTWF4RGlzY2hhcmdlJE1heERpc2NoYXJnZU1vbnRoID0gYXMubnVtZXJpYyhEZWx0YU1heERpc2NoYXJnZSRNYXhEaXNjaGFyZ2VNb250aCkKCgojam9pbiB3aXRoIG90aGVyIGRlbHRhIGRhdGEKRGVsdGFNYXhNaW5EaXNjaGFyZ2UgPC0gbGVmdF9qb2luKERlbHRhTWF4TWluLCBEZWx0YU1heERpc2NoYXJnZSwgYnkgPSAnRGVsdGEnKQoKI2NhbGN1bGF0ZSBvZmZzZXQKRGVsdGFNYXhNaW5EaXNjaGFyZ2UgPC0gRGVsdGFNYXhNaW5EaXNjaGFyZ2UgJT4lCiAgbXV0YXRlKCBEaXNzT2ZmID0gaWZfZWxzZShhYnMoTWF4RGlzY2hhcmdlTW9udGggLSBNYXhNZWFuTkRTU0ltb250aCkgPiA2LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgMTIgLSBhYnMoTWF4RGlzY2hhcmdlTW9udGggLSBNYXhNZWFuTkRTU0ltb250aCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhYnMoTWF4RGlzY2hhcmdlTW9udGggLSBNYXhNZWFuTkRTU0ltb250aCkpCiAgICAgICAgICApCgojQ29tcGFyZSBvZmZzZXQgd2l0aCBORFNTSSAoZGVsdGFtYXhtaW4kbWF4bWVhbk5EU1NJbW9udGgpCmdncGxvdChEZWx0YU1heE1pbkRpc2NoYXJnZSwgYWVzKHkgPSBEZWx0YSwgeCA9IERpc3NPZmYpKSArIGdlb21fcG9pbnQoKSArIAogIHNjYWxlX3hfZGlzY3JldGUobGltaXRzID0gYygxOjYpLCBicmVha3MgPSBjKDE6NikpICsKICBleHBhbmRfbGltaXRzKHggPSBjKDAsNikpICArIAogIGdndGl0bGUoIkRpc09mZnNldCIpCmBgYAoKTG9vayBhdCBHUkRDIGRhdGEgYnkgbGF0aXR1ZGU6CgpgYGB7cn0KI2pvaW4gbGF0IGRhdGEKRGVsdGFEYXRhd0xvY2F0aW9ucyA8LSBsZWZ0X2pvaW4oRGVsdGFNYXhNaW5EaXNjaGFyZ2UsIERlbHRhTG9jYXRpb25zLCBieSA9IGMoIkRlbHRhIiA9ICJEZWx0YXMiKSkKCkRlbHRhRGF0YXdMb2NhdGlvbnMgPC0gRGVsdGFEYXRhd0xvY2F0aW9ucyAlPiUKICBtdXRhdGUoQWJzb2x1dGVfTGF0aXR1ZGU9IGFicyhMYXQpKQoKIyBwbG90IG9mZnNldCBvbiBncmFwaCBieSBsYXQKZ2dwbG90KERlbHRhRGF0YXdMb2NhdGlvbnMsIGFlcyh4ID0gQWJzb2x1dGVfTGF0aXR1ZGUsIHkgPSBEaXNzT2ZmKSkgKyBnZW9tX3BvaW50KCkgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50KGxvdyA9ICJ5ZWxsb3ciLCBoaWdoID0gInJlZCIsIG5hLnZhbHVlID0gTkEpIAogICMrIGdlb21fc21vb3RoKG1hcHBpbmcgPSBhZXMoeCA9IEFic29sdXRlX0xhdGl0dWRlLCB5ID0gRGlzc09mZiwgKSwgbWV0aG9kPWxtICkgCgojZ2dzYXZlKCJEaXNPZmZzZXQucGRmIiwgd2lkdGggPSA2LCBoZWlnaHQgPSA0KQpgYGAKCkFuZCBub3cgb24gYSBtYXA6CmBgYHtyfQojcGxvdCBvZmZzZXQgb24gbWFwCkRlbHRhRGlzT2Zmc2V0TWFwIDwtIHdvcmxkICsKICBnZW9tX3BvaW50KGFlcyh4ID0gTG9uLCB5ID0gTGF0LCBjb2xvciA9IERpc3NPZmYpLAogICAgICAgICAgICAgZGF0YSA9IERlbHRhRGF0YXdMb2NhdGlvbnMsIAogICAgICAgICAgICAgc2l6ZSA9IDUpICsgc2NhbGVfY29sb3JfZ3JhZGllbnQoIGhpZ2ggPSAicmVkIiwgbG93ICA9ICJ5ZWxsb3ciKSArCiAgZ2d0aXRsZSgiT2Zmc2V0IEJldHdlZW4gR1JEQyBkaXNjaGFyZ2UgcGVhayBhbmQgTkRTU0kgcGVhayBpbiB3YXRlciIpCgpEZWx0YURpc09mZnNldE1hcAojZ2dzYXZlKCJEZWx0YU9mZnNldE1hcC5wZGYiLCB3aWR0aCA9IDYsIGhlaWdodCA9IDQpCgpgYGAKCgoK